package org.study.local.boot.util;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文件上传工具类
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2024年04月28日
 */
@Slf4j
@UtilityClass
public class LocalUploadUtils {
    // 允许的文件格式、大小(单位是MB)
    public final List<String> ALLOWED_IMG_TYPE = Lists.newArrayList(".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp");
    public final long ALLOWED_IMG_SIZE = 10L;
    public final List<String> ALLOWED_DOC_TYPE = Lists.newArrayList(".txt", ".md", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx");
    public final long ALLOWED_DOC_SIZE = 5L;
    public final List<String> ALLOWED_VIDEO_TYPE = Lists.newArrayList(".mp4", ".avi", ".mov", ".3gp");
    public final long ALLOWED_VIDEO_SIZE = 20L;
    public final List<String> ALLOWED_OTHER_TYPE = Lists.newArrayList(".zip", ".dwg", ".dxf");
    public final long ALLOWED_OTHER_SIZE = 10L;

    public static String upload(String savePath, MultipartFile file) {
        File savePathFile = new File(savePath);
        if (!savePathFile.exists()) {
            // 若不存在该目录，则创建目录
            savePathFile.mkdirs();
        }
        // 生成唯一文件名
        String filename = IdUtil.getSnowflakeNextIdStr() + getMultipartFileSuffix(file);
        try {
            // 将文件保存指定目录
            file.transferTo(new File(savePath, filename));
        } catch (IOException ex) {
            ex.printStackTrace();
            throw new RuntimeException("保存文件异常");
        }
        // 返回文件名称
        return filename;
    }

    /**
     * 获取文件后缀名，如.jpg、.pdf
     */
    public String getMultipartFileSuffix(MultipartFile file) {
        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        return suffix;
    }

    /**
     * 获取文件后缀名，如.jpg、.pdf
     */
    public String getFileSuffix(File file) {
        String filename = file.getName();
        String suffix = filename.substring(filename.lastIndexOf("."));
        return suffix;
    }

    /**
     * 校验文件格式是否为指定格式
     *
     * @param suffix     文件后缀名，如.jpg、.pdf
     * @param allowTypes 允许的文件类型列表
     */
    public boolean isFileTypeAllowed(String suffix, List<String> allowTypes) {
        boolean isFileTypeAllowed = false;
        if (CollectionUtils.isNotEmpty(allowTypes) && StringUtils.isNotBlank(suffix)) {
            isFileTypeAllowed = allowTypes.contains(suffix.toLowerCase());
        }
        log.info("是否允许：{}，当前文件后缀名：{}，系统允许的文件类型：{}", isFileTypeAllowed, suffix, JSON.toJSONString(allowTypes));
        return isFileTypeAllowed;
    }

    /**
     * 判断文件是否超过指定大小
     *
     * @param fileSize     文件大小，单位是字节
     * @param expectedSize 文件大小上限，单位是MB
     */
    public boolean isFileSizeOver(long fileSize, long expectedSize) {
        long expectedBytes = expectedSize << 20;
        boolean isFileSizeOver = fileSize >= expectedBytes;
        log.info("是否超限：{}，当前文件大小：{}，系统配置的文件大小阈值：{}", isFileSizeOver, fileSize, expectedBytes);
        return isFileSizeOver;
    }

    /**
     * 文件后缀校验
     *
     * @param suffix      文件实际后缀
     * @param allowSuffix 允许的文件后缀
     * @return
     */
    private boolean isFileSuffixAllowed(String suffix, List<String> allowSuffix) {
        List<String> lowerCaseList = allowSuffix.stream()
                .map(item -> item.toLowerCase())
                .collect(Collectors.toList());
        return lowerCaseList.contains(suffix.toLowerCase());
    }

    /**
     * 文件大小、后缀校验
     *
     * @param fileSize 文件实际大小，单位是字节
     * @param suffix   文件实际后缀
     * @return
     */
    public void checkFileSizeAndSuffix(long fileSize, String suffix) {
        if (isFileSuffixAllowed(suffix, ALLOWED_IMG_TYPE)) {
            isFileSizeOver(fileSize, ALLOWED_IMG_SIZE);
        } else if (isFileSuffixAllowed(suffix, ALLOWED_DOC_TYPE)) {
            isFileSizeOver(fileSize, ALLOWED_DOC_SIZE);
        } else if (isFileSuffixAllowed(suffix, ALLOWED_VIDEO_TYPE)) {
            isFileSizeOver(fileSize, ALLOWED_VIDEO_SIZE);
        } else if (isFileSuffixAllowed(suffix, ALLOWED_OTHER_TYPE)) {
            isFileSizeOver(fileSize, ALLOWED_OTHER_SIZE);
        } else {
            throw new IllegalArgumentException("不允许上传" + suffix + "类型的文件");
        }
    }
}
